﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace Zsea.HTML
{
    [DebuggerDisplay("{Name}")]
    public class Node
    {
        // Fields
        internal List<Node> _AllNode = new List<Node>();
        private string _innerHTML;
        private string _innerText;
        internal string _name;
        private string _outerHtml;

        // Methods
        public Node()
        {
            this.Children = new NodeCollection();
            this.Children._Parent = this;
            this.Attributes = new AttributeCollection();
        }

        public List<Node> FindAll(Predicate<Node> match)
        {
            return this._AllNode.FindAll(match);
        }

        public List<Node> FindAll(string name)
        {
            return this._AllNode.FindAll(delegate(Node o)
            {
                return o.Name.ToUpper() == name.ToUpper();
            });
        }

        internal List<Node> SetXPath(string xPath, Document doc)
        {
            this._AllNode.Add(this);
            this.XPath = xPath;
            doc.pathCollection[xPath.ToUpper()] = this;
            Dictionary<string, int> dictionary = new Dictionary<string, int>();
            for (int i = 0; i < this.Children.Count; i++)
            {
                int num2 = 0;
                if (dictionary.ContainsKey(this.Children[i].Name.ToUpper()))
                {
                    num2 = dictionary[this.Children[i].Name.ToUpper()] + 1;
                    dictionary[this.Children[i].Name.ToUpper()] = num2;
                }
                else
                {
                    dictionary[this.Children[i].Name.ToUpper()] = 0;
                }
                this._AllNode.AddRange(this.Children[i].SetXPath(string.Concat(new object[] { xPath, "/", this.Children[i].Name, "[", num2, "]" }), doc));
            }
            return this._AllNode;
        }

        public Node SingleNode(Predicate<Node> match)
        {
            return this._AllNode.Find(match);
        }

        public Node SingleNode(string name)
        {
            return this._AllNode.Find(delegate(Node o)
            {
                return o.Name.ToUpper() == name.ToUpper();
            });
        }

        // Properties
        public AttributeCollection Attributes
        {

            get;
            private set;
        }

        public NodeCollection Children
        {

            get;
            private set;
        }

        internal string endFlag
        {

            get;

            set;
        }

        public string InnerHTML
        {
            get
            {
                if ((this.NodeType == NodeType.Comment) || (this.NodeType == NodeType.Text))
                {
                    return this.startFlag;
                }
                if (this._innerHTML == null)
                {
                    for (int i = 0; i < this.Children.Count; i++)
                    {
                        this._innerHTML = this._innerHTML + this.Children[i].OuterHTML;
                    }
                }
                return this._innerHTML;
            }
        }

        public string InnerText
        {
            get
            {
                if (this.NodeType == NodeType.Comment)
                {
                    return this.OuterHTML;
                }
                if (this.NodeType == NodeType.Text)
                {
                    return this.startFlag;
                }
                if (this._innerText == null)
                {
                    this._innerText = string.Empty;
                    for (int i = 0; i < this.Children.Count; i++)
                    {
                        this._innerText = this._innerText + this.Children[i].InnerText;
                    }
                }
                return this._innerText;
            }
        }

        public string Name
        {
            get
            {
                if (this._name == null)
                {
                    return ("#" + this.NodeType.ToString());
                }
                return this._name;
            }
            internal set
            {
                this._name = value;
            }
        }

        public NodeType NodeType
        {

            get;

            internal set;
        }

        public string OuterHTML
        {
            get
            {
                if (this._outerHtml == null)
                {
                    if ((this.NodeType == NodeType.Comment) || (this.NodeType == NodeType.Text))
                    {
                        this._outerHtml = this.startFlag;
                    }
                    else
                    {
                        this._outerHtml = this.startFlag + this.InnerHTML + this.endFlag;
                    }
                }
                return this._outerHtml;
            }
        }

        public Node Parent
        {

            get;

            internal set;
        }

        internal string startFlag
        {

            get;

            set;
        }

        public string XPath
        {

            get;


            private set;
        }
    }





}
